import os
import logging
import pandas as pd
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
                             QFileDialog, QTextEdit, QProgressBar, QTableWidget, QTableWidgetItem, QMessageBox)
from PyQt5.QtCore import Qt, QThread, pyqtSignal

from core.project import ProjectManagerCore
from core.database import Database
from core.file_scanner import scan_directory
from core.dispatcher import dispatch_parser
from core.bank_config import BANK_CODES

class Worker(QThread):
    progress = pyqtSignal(int)
    log = pyqtSignal(str)
    preview_ready = pyqtSignal(object, object)  # (account_df, trans_df)
    done = pyqtSignal(int, int)  # (accounts_cnt, trans_cnt)

    def __init__(self, root_dir):
        super().__init__()
        self.root_dir = root_dir

    def run(self):
        total_accounts = 0
        total_trans = 0
        self.log.emit(f"开始扫描根目录: {self.root_dir}")
        # 遍历一级银行目录
        bank_dirs = [d for d in os.listdir(self.root_dir) if os.path.isdir(os.path.join(self.root_dir, d))]
        total = len(bank_dirs) if bank_dirs else 1
        for idx, bank_dir in enumerate(bank_dirs, start=1):
            bank_path = os.path.join(self.root_dir, bank_dir)
            bank_code = bank_dir[:3] if bank_dir[:3].isdigit() else None
            if bank_code not in BANK_CODES:
                self.log.emit(f"跳过目录（非银行代码开头）: {bank_dir}")
                self.progress.emit(int(idx/total*100))
                continue

            self.log.emit(f"处理银行: {bank_dir} ({bank_code})")
            excel_files = scan_directory(bank_path)
            for file_path in excel_files:
                try:
                    account_df, trans_df = dispatch_parser(bank_code, file_path)
                    total_accounts += len(account_df) if account_df is not None else 0
                    total_trans += len(trans_df) if trans_df is not None else 0
                    # 发送第一份预览
                    self.preview_ready.emit(account_df.head(10), trans_df.head(10))
                    self.log.emit(f"解析完成: {file_path}")
                except Exception as e:
                    self.log.emit(f"解析失败: {file_path} -> {e}")
            self.progress.emit(int(idx/total*100))
        self.done.emit(total_accounts, total_trans)

class TabEntry(QWidget):
    def __init__(self, project):
        super().__init__()
        self.project = project
        self.db_path = ProjectManagerCore().get_db_path(project)
        self.db = Database(self.db_path)

        self._build_ui()

        # 日志对象
        self.logger = logging.getLogger(__name__)

    def _build_ui(self):
        layout = QVBoxLayout()

        top = QHBoxLayout()
        self.lbl = QLabel("录入系统：选择银行数据根目录（每家银行一个子文件夹，文件为Excel）")
        self.btn_select = QPushButton("选择目录并解析")
        self.btn_import = QPushButton("导入到数据库")
        self.btn_import.setEnabled(False)

        top.addWidget(self.lbl)
        top.addStretch(1)
        top.addWidget(self.btn_select)
        top.addWidget(self.btn_import)

        self.log_box = QTextEdit(); self.log_box.setReadOnly(True)
        self.progress = QProgressBar(); self.progress.setValue(0)

        self.preview_accounts = QTableWidget()
        self.preview_trans = QTableWidget()

        layout.addLayout(top)
        layout.addWidget(self.progress)
        layout.addWidget(QLabel("日志输出:"))
        layout.addWidget(self.log_box, stretch=1)
        layout.addWidget(QLabel("开户信息预览:"))
        layout.addWidget(self.preview_accounts)
        layout.addWidget(QLabel("交易流水预览:"))
        layout.addWidget(self.preview_trans)

        self.setLayout(layout)

        self.btn_select.clicked.connect(self.choose_dir)
        self.btn_import.clicked.connect(self.import_to_db)

        self._last_results = []  # list of (account_df, trans_df)

    def choose_dir(self):
        root_dir = QFileDialog.getExistingDirectory(self, "选择银行数据根目录")
        if not root_dir:
            return
        self.log_box.append(f"选择目录: {root_dir}")
        # 开线程做解析
        self.worker = Worker(root_dir)
        self.worker.log.connect(self.log_box.append)
        self.worker.progress.connect(self.progress.setValue)
        self.worker.preview_ready.connect(self._update_preview)
        self.worker.done.connect(self._on_done)
        # 收集结果：通过 monkey-patch 把每次预览也存起来（轻量）
        def collect_preview(acc, trans):
            self._last_results.append((acc, trans))
        self.worker.preview_ready.connect(collect_preview)
        self._last_results.clear()
        self.progress.setValue(0)
        self.btn_import.setEnabled(False)
        self.worker.start()

    def _update_preview(self, account_df, trans_df):
        self._fill_table(self.preview_accounts, account_df)
        self._fill_table(self.preview_trans, trans_df)

    def _on_done(self, acc_cnt, trans_cnt):
        self.log_box.append(f"完成解析：开户 {acc_cnt} 条，流水 {trans_cnt} 条")
        self.btn_import.setEnabled(True)

    def _fill_table(self, table: QTableWidget, df: pd.DataFrame):
        if df is None or df.empty:
            table.clear()
            table.setRowCount(0); table.setColumnCount(0)
            return
        cols = list(df.columns)
        rows = df.shape[0]
        table.setColumnCount(len(cols))
        table.setRowCount(rows)
        table.setHorizontalHeaderLabels([str(c) for c in cols])
        for i in range(rows):
            for j, c in enumerate(cols):
                v = df.iloc[i, j]
                table.setItem(i, j, QTableWidgetItem("" if pd.isna(v) else str(v)))
        table.resizeColumnsToContents()

    def import_to_db(self):
        if not self._last_results:
            QMessageBox.warning(self, "提示", "没有可导入的数据，请先解析目录。")
            return
        total_a = total_t = 0
        for acc_df, trans_df in self._last_results:
            try:
                total_a += self.db.insert_accounts(acc_df)
                total_t += self.db.insert_transactions(trans_df)
            except Exception as e:
                self.log_box.append(f"写入数据库失败: {e}")
        self.log_box.append(f"写入数据库完成：账户 {total_a} 条，流水 {total_t} 条")
        QMessageBox.information(self, "完成", f"导入完成：账户 {total_a}，流水 {total_t}")
